<template>
  <div class="default-main page">
    <PageSearch
      ref="pageSearchRef"
      :pageName="pageName"
      :searchConfig="searchConfigComputed"
    ></PageSearch>
    <PageContent
      ref="pageContentRef"
      :pageName="pageName"
      :contentConfig="contentConfigComputed"
      :autoDesc="false"
      :dictMap="dictMap"
      :tableListener="tableListener"
      :tableSelected="tableSelected"
      :permission="permission"
      :requestBaseUrl="requestBaseUrl"
      :tableHideItems="tableHideItems"
      :idKey="'fileId'"
      @beforeSend="beforeSend"
      @addClick="addClick"
      @editBtnClick="editBtnClick"
      @onChangeShowColumn="onChangeShowColumn"
      @deleteClick="handleDelete"
      @editMoreClick="editMoreClick"
    >
      <template #handleLeft>
        <el-button
          type="warning"
          class="ml12 order16"
          v-hasPermi="['system:files:export']"
          @click="handleExport"
        >
          <SvgIcon size="14" iconClass="download" />
          <span class="ml6">导出</span>
        </el-button>
      </template>
      
      <!-- URL地址自定义插槽 -->
      <template #storagePathSlot="{ backData }">
        <div class="storage-path-preview">
          <a 
            :href="getFileUrl(backData.storagePath)" 
            target="_blank" 
            class="file-link"
            title="点击查看文件"
          >
            {{ getFileName(backData.storagePath) }}
          </a>
        </div>
        </template>
      
      <!-- 是否加密自定义插槽 -->
      <template #isEncryptedSlot="{ backData }">
        <div class="encryption-status">
          <el-tag
            :type="getIsEncryptedValue(backData.isEncrypted) === 'Y' ? 'danger' : 'success'"
            effect="light"
          >
            {{ getIsEncryptedValue(backData.isEncrypted) === 'Y' ? '是' : '否' }}
          </el-tag>
          
          <!-- 如果已加密，显示查看密钥图标 -->
          <el-tooltip 
            v-if="getIsEncryptedValue(backData.isEncrypted) === 'Y' && backData.encryptionKey" 
            :content="'密钥: ' + backData.encryptionKey"
            placement="top"
          >
            <el-icon class="key-icon"><Key /></el-icon>
          </el-tooltip>
        </div>
      </template>
    </PageContent>
    <PageDialog
      ref="dialogRef"
      :width="getWidth(dialogWidth)"
      :pageName="pageName"
      :dialogConfig="dialogConfigComputed"
      :infoInit="infoInit"
      :search="search"
      :isEditMore="isEditMore"
      :requestBaseUrl="requestBaseUrl"
      @editNext="editNext"
      @beforeCommit="handleBeforeCommit"
      @beforeSave="beforeSubmit"
      @uploadSuccess="handleUploadSuccess"
    >
    </PageDialog>
  </div>
</template>

<script setup name="Files">
import { nextTick, watch } from 'vue'
import { listFiles, getFiles, delFiles, addFiles, updateFiles } from "@/api/system/files"
import useDialog from '@/hooks/useDialog'
import getComputedConfig from '@/hooks/getPageConfig'
import { inject } from 'vue'
import to from '@/utils/to'
import { systemBaseUrl } from '@/api/config/base.js'
import getSearchConfig from './config/searchConfig'
import getContentConfig from './config/contentConfig'
import getDialogConfig from './config/dialogConfig'
import { Key } from '@element-plus/icons-vue'

const proxy = inject('proxy')
const { sys_yes_no } = proxy.useDict('sys_yes_no')

// 页面名称
const pageName = 'files'
// 请求基础URL
const requestBaseUrl = systemBaseUrl
// 页面搜索组件引用
const pageSearchRef = ref(null)
// 页面内容组件引用
const pageContentRef = ref(null)

// 对话框需要隐藏的项
const dialogHideItems = ref([])
// 表格需要隐藏的项
const tableHideItems = ref([])
// 数据字典映射
const dictMap = {
  isEncrypted: sys_yes_no
}

// 搜索配置
const searchConfig = getSearchConfig()
const searchConfigComputed = computed(() => {
  return getComputedConfig(searchConfig, dictMap)
})

// 表格选中项
const tableSelected = ref([])
// 表格事件监听
const tableListener = {
  selectionChange: (selected) => {
    tableSelected.value = selected
  },
}

// 内容配置
const contentConfig = getContentConfig()
const contentConfigComputed = computed(() => {
  contentConfig.hideItems = tableHideItems
  return contentConfig
})

// 对话框配置
const dialogConfig = getDialogConfig()
const dialogConfigComputed = computed(() => {
  dialogConfig.hideItems = dialogHideItems
  return getComputedConfig(dialogConfig, dictMap)
})

/** 确保isEncrypted在提交到后端前是整数 */
const convertIsEncryptedToInt = (formData) => {
  if (formData) {
    console.log("转换前isEncrypted:", formData.isEncrypted, typeof formData.isEncrypted)
    if (formData.isEncrypted === 'Y') {
      formData.isEncrypted = 1
    } else if (formData.isEncrypted === 'N') {
      formData.isEncrypted = 0
    } else if (formData.isEncrypted === '1') {
      // 已经是数字形式的字符串，转为数字
      formData.isEncrypted = 1
    } else if (formData.isEncrypted === '0') {
      // 已经是数字形式的字符串，转为数字
      formData.isEncrypted = 0
    }
    console.log("转换后isEncrypted:", formData.isEncrypted, typeof formData.isEncrypted)
  }
  return formData
}

/** 将isEncrypted的任何形式值转为Y/N显示 */
const getIsEncryptedValue = (value) => {
  if (value === 1 || value === '1' || value === 'Y' || value === true) {
    return 'Y'
  }
  return 'N'
}

/** 提交前处理表单数据 */
const beforeSubmit = () => {
  console.log("执行表单提交前处理...")
  if (dialogRef.value && dialogRef.value.formData) {
    // 打印整个表单数据进行检查
    console.log("提交前的表单数据:", JSON.stringify(dialogRef.value.formData))
    convertIsEncryptedToInt(dialogRef.value.formData)
    // 打印转换后的表单数据进行比对
    console.log("转换后的表单数据:", JSON.stringify(dialogRef.value.formData))
  }
}

/** 监听是否加密字段，控制加密密钥的显示/隐藏 */
const watchEncryption = (form) => {
  if (form && typeof form.isEncrypted !== 'undefined') {
    // 对于前端显示，任何形式的值都转为Y/N形式
    form.isEncrypted = getIsEncryptedValue(form.isEncrypted)
    
    // 如果isEncrypted为'Y'（即加密），则显示加密密钥字段
    if (form.isEncrypted === 'Y') {
      // 显示加密密钥字段
      if (dialogHideItems.value.includes('encryptionKey')) {
        dialogHideItems.value = dialogHideItems.value.filter(item => item !== 'encryptionKey')
      }
    } else {
      // 隐藏加密密钥字段
      if (!dialogHideItems.value.includes('encryptionKey')) {
        dialogHideItems.value = [...dialogHideItems.value, 'encryptionKey']
      }
      // 清空加密密钥
      if (form.encryptionKey) {
        form.encryptionKey = ''
      }
    }
  }
}

/** 添加回调函数 */
const addCallBack = () => {
  // 重置隐藏项
  dialogHideItems.value = []
  
  // 默认隐藏加密密钥字段，直到选择"是"
  if (!dialogHideItems.value.includes('encryptionKey')) {
    dialogHideItems.value = ['encryptionKey']
  }
  
  // 设置默认值
  nextTick(() => {
    if (dialogRef.value && dialogRef.value.formData) {
      dialogRef.value.formData.isEncrypted = 'N' // 默认不加密
      dialogRef.value.formData.createdAt = new Date().toISOString().slice(0, 19).replace('T', ' ') // 设置当前时间
      
      // 确保立即应用隐藏项
      watchEncryption(dialogRef.value.formData)
      
      // 监听是否加密变化
      watch(() => dialogRef.value.formData.isEncrypted, (newVal) => {
        watchEncryption(dialogRef.value.formData)
      }, { immediate: true })
    }
  })
}

/** 编辑回调函数 */
const editCallback = (item, type, res) => {
  console.log('编辑回调被触发', JSON.stringify(item), type, res)
  // 重置隐藏项
  dialogHideItems.value = []
  isEditMore.value = type
  
  // 根据是否加密值控制加密密钥字段
  nextTick(() => {
    if (dialogRef.value && dialogRef.value.formData) {
      console.log('编辑初始表单数据:', JSON.stringify(dialogRef.value.formData))
      
      // 确保所有必要字段都存在，避免后端500错误
      if (!dialogRef.value.formData.fileId && item.fileId) {
        dialogRef.value.formData.fileId = item.fileId;
      }
      
      // 在编辑时，确保isEncrypted字段的格式正确
      if (typeof dialogRef.value.formData.isEncrypted === 'number') {
        // 如果是数字，转为字符串显示
        dialogRef.value.formData.isEncrypted = dialogRef.value.formData.isEncrypted === 1 ? 'Y' : 'N'
        console.log('编辑时isEncrypted转换为:', dialogRef.value.formData.isEncrypted)
      }
      
      // 检查必填字段是否存在
      const requiredFields = ['fileId', 'fileName', 'fileType', 'storagePath', 'isEncrypted'];
      let missingFields = [];
      requiredFields.forEach(field => {
        if (dialogRef.value.formData[field] === undefined) {
          console.warn(`编辑表单缺少必填字段: ${field}`);
          missingFields.push(field);
          
          // 如果item中有这个字段，则从item中获取
          if (item[field] !== undefined) {
            dialogRef.value.formData[field] = item[field];
            console.log(`从item中获取字段: ${field} = ${item[field]}`);
          }
        }
      });
      
      if (missingFields.length > 0) {
        console.warn('发现缺失字段，已尝试填充:', missingFields.join(', '));
      }
      
      // 确保立即应用隐藏项
      watchEncryption(dialogRef.value.formData)
      
      // 监听是否加密变化
      watch(() => dialogRef.value.formData.isEncrypted, (newVal) => {
        console.log('isEncrypted值变化:', newVal)
        watchEncryption(dialogRef.value.formData)
      }, { immediate: true })
    }
  })
}

/** 表单提交前处理 */
const handleBeforeCommit = (form) => {
  console.log("handleBeforeCommit原始数据:", JSON.stringify(form))

  // 确保isEncrypted是正确的字符串格式，用于表单验证
  form.isEncrypted = getIsEncryptedValue(form.isEncrypted)
  
  // 如果选择不加密，清空加密密钥
  if (form.isEncrypted === 'N' && form.encryptionKey) {
    form.encryptionKey = ''
  }
  
  // 如果选择加密但未提供密钥，提示用户
  if (form.isEncrypted === 'Y' && !form.encryptionKey) {
    proxy.$modal.msgWarning('您选择了加密文件，但未提供加密密钥！')
    return false
  }
  
  // 转换isEncrypted字段的值为整数
  const processedForm = { ...form };  // 创建副本，避免直接修改原始对象
  
  // 转换isEncrypted为数字
  if (processedForm.isEncrypted === 'Y') {
    processedForm.isEncrypted = 1
  } else if (processedForm.isEncrypted === 'N') {
    processedForm.isEncrypted = 0
  }
  
  console.log("handleBeforeCommit处理后:", JSON.stringify(processedForm))
  
  // 确保编辑时提交的数据结构完整
  if (processedForm.fileId) {
    // 这是编辑操作，确保所有必要字段都存在
    console.log("编辑操作，fileId:", processedForm.fileId)
    
    // 检查必要字段
    const requiredFields = ['fileId', 'fileName', 'fileType', 'storagePath', 'isEncrypted'];
    const missingFields = requiredFields.filter(field => processedForm[field] === undefined);
    
    if (missingFields.length > 0) {
      console.error('提交表单缺少必填字段:', missingFields.join(', '));
      proxy.$modal.msgError(`表单缺少必填字段: ${missingFields.join(', ')}`);
      return false;
    }
  }
  
  return processedForm
}

const isEditMore = ref(false)

/** 多选编辑按钮点击 */
const editMoreClick = () => {
  if (tableSelected.value.length > 0) {
    const data = tableSelected.value[0]
    pageContentRef.value?.editClick(data, true)
    nextTick(() => {
      const newArray = tableSelected.value.slice(1)
      dialogRef.value?.changeSelected(newArray)
    })
  }
}

/** 编辑下一条记录 */
const editNext = (data) => {
  console.log('editNext被调用，数据:', data)
  if (pageContentRef.value && pageContentRef.value.editClick) {
    pageContentRef.value.editClick(data, true)
  } else {
    console.error('pageContentRef.value不存在或没有editClick方法')
  }
}

const [dialogRef, infoInit, addClick, editBtnClick] = useDialog(
  addCallBack,
  editCallback,
  '添加',
  '编辑'
)

// 对话框宽度
const dialogWidth = ref('600px')
// 搜索数据
const searchData = computed(() => {
  return pageContentRef.value?.finalSearchData
})

/** 获取宽度值 */
const getWidth = (width) => {
  if (typeof width === 'number') {
    return width + 'px'
  } 
  return width
}

/** 搜索方法 */
const search = () => {
  pageSearchRef.value?.search()
}

/** 请求前处理查询参数 */
const beforeSend = (queryInfo) => {
  // 处理日期范围
  if (queryInfo.dateRange && Array.isArray(queryInfo.dateRange)) {
    const dateRange = queryInfo.dateRange
    queryInfo['params[beginTime]'] = dateRange[0]
    queryInfo['params[endTime]'] = dateRange[1]
    delete queryInfo.dateRange
  }
  
  // 转换isEncrypted字段
  if (queryInfo.isEncrypted === 'Y') {
    queryInfo.isEncrypted = 1
  } else if (queryInfo.isEncrypted === 'N') {
    queryInfo.isEncrypted = 0
  }
}

// 权限配置
const permission = ref({
  add: 'system:files:add',
  edit: 'system:files:edit',
  del: 'system:files:remove',
})

/** 列显示变更处理 */
const onChangeShowColumn = (filterArr) => {
  tableHideItems.value = filterArr
}

/** 导出按钮操作 */
const handleExport = () => {
  proxy.download(
    'system/files/export',
    {
      ...searchData.value,
    },
    `files_${new Date().getTime()}.xlsx`
  )
}

/** 获取文件URL */
const getFileUrl = (path) => {
  if (!path) return ''
  return path.startsWith('http') 
    ? path 
    : import.meta.env.VITE_APP_BASE_API + path
}

/** 获取文件名 */
const getFileName = (path) => {
  if (!path) return ''
  const parts = path.split('/')
  return parts[parts.length - 1]
}

/** 文件上传成功的处理函数 */
const handleUploadSuccess = (response, file, item) => {
  console.log('文件上传成功:', response, file, item)
  
  if (dialogRef.value && dialogRef.value.formData) {
    // 将上传文件的路径设置到表单中
    dialogRef.value.formData.storagePath = response.fileName
    
    // 自动填充文件名
    dialogRef.value.formData.fileName = file.name
    
    // 获取文件扩展名
    const fileExt = file.name.split('.').pop().toLowerCase()
    
    // 设置文件类型为文件扩展名
    dialogRef.value.formData.fileType = fileExt
    
    // 如果用户ID为空，设置为当前登录用户ID
    if (!dialogRef.value.formData.userId) {
      const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}')
      dialogRef.value.formData.userId = userInfo.userId || ''
    }
  }
}

/** 删除文件 */
const handleDelete = async (row) => {
  const fileIds = Array.isArray(row) ? row.map(item => item.fileId) : row.fileId
  if (!fileIds || (Array.isArray(fileIds) && fileIds.length === 0)) {
    proxy.$modal.msgError('未获取到有效Id')
    return
  }
  
  proxy.$modal.confirm(`确认删除文件编号为"${fileIds}"的数据项？`).then(async () => {
    const [res, err] = await to(delFiles(fileIds))
    if (res) {
      proxy.$modal.msgSuccess('删除成功')
      search()
    } else {
      proxy.$modal.msgError(err.message || '删除失败')
    }
  }).catch(() => {})
}
</script>

<style scoped lang="scss">
.page {
  :deep(.statusClass .el-radio-group) {
    width: 100%;
    justify-content: space-between;
    .el-radio {
      margin-right: 0;
    }
  }
}

.storage-path-preview {
  display: flex;
  align-items: center;
  width: 100%;
  
  .file-link {
    color: var(--el-color-primary);
    text-decoration: none;
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    
    &:hover {
      text-decoration: underline;
    }
  }
}

.encryption-status {
  display: flex;
  align-items: center;
  gap: 8px;
  
  .key-icon {
    cursor: pointer;
    color: var(--el-color-warning);
    font-size: 16px;
  }
}
</style>
